/*
 * Copyright (c) 宜品生鲜
 */

package com.zhangfei.order.server.aop;


import com.google.common.base.Throwables;
import com.zhangfei.Common;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 处理所有grpcImpl中出现的异常
 */
@Slf4j
@Order(2)
@Aspect
@Component
public class GrpcExceptionProcessAop {


    //其他项目模块要使用，自己定义个pointCut 一个Before
    @Pointcut("execution(public * com.zhangfei.order.server.grpc..*.*(..))")
    public void grpcExceptionService() {
    }

    /**
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("grpcExceptionService()")
    public Object grpcException(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            return joinPoint.proceed();
        } catch (Throwable throwable) {
            List<Object> list = Arrays.asList(joinPoint.getArgs());
            log.error("GrpcExceptionProcessAop  接口代理接口执行异常, 入参 {} caused by {} ", list, Throwables.getStackTraceAsString(throwable));
            Object[] arguments = joinPoint.getArgs();
            Class targetClass = joinPoint.getTarget().getClass();
            String methodName = joinPoint.getSignature().getName();
            List<Class> parameter = new ArrayList<>();
            for (Object o : arguments) {
                parameter.add(o.getClass());
            }
            Method method = targetClass.getMethod(methodName, parameter.toArray(new Class[parameter.size()]));
            Class returnClass = method.getReturnType();
            Object returnObject = null;
            try {
                Object builder = returnClass.getMethod("newBuilder").invoke(returnClass);
                builder.getClass().getMethod("setCodeInfo", Common.CodeInfo.class).invoke(builder,Common.CodeInfo.newBuilder().setCode(0001).setMsg("业务异常").build());
                returnObject = builder.getClass().getMethod("build").invoke(builder);
                log.info("grpcException returnObject:{}",returnObject);
            } catch (Exception e) {
                log.warn("通用异常业务逻辑处理异常，可能返回值没有定义codeInfo对象", e);
            }
            if (returnObject != null) {
                return returnObject;
            }
            throw throwable;
        }
    }

}
